#ifndef COMMON_UTIL_H
#define COMMON_UTIL_H

// --------------- 必要的系统头文件 ---------------
#include <arpa/inet.h>   // 网络地址转换（htonl等）
#include <sys/socket.h>  // 套接字操作（socket/bind等）
#include <unistd.h>      // 系统调用（close等）
#include <chrono>        // 时间类型（time_point/duration）
#include <condition_variable>  // 条件变量（用于LockQueue）
#include <functional>    // 函数对象（DeferClass的构造参数）
#include <mutex>         // 互斥锁（用于LockQueue）
#include <queue>         // 底层队列（LockQueue的基础）
#include <string>        // 字符串类型
#include <ostream>       // 输出流（Op类的operator<<）

// --------------- 外部库依赖 ---------------
#include <boost/archive/text_iarchive.hpp>          // Boost反序列化
#include <boost/archive/text_oarchive.hpp>          // Boost序列化
#include <boost/serialization/access.hpp>           // 提供 access 类（访问私有成员）
#include <boost/serialization/serialization.hpp>    // 序列化基础框架
    
// --------------- 项目内部依赖 ---------------
#include "config.h"     // 全局配置常量（DEBUG等）

/**
 * @namespace common
 * @brief 公共模块命名空间，包含全局配置、工具类等通用组件
 */
namespace common {

/**
 * @brief 延迟执行工具类（RAII机制）
 * @details 利用对象生命周期管理，在析构时自动执行注册的函数
 *          常用于资源释放、状态恢复等需要确保执行的操作
 * @tparam F 函数类型，支持任意可调用对象
 */
template <class F>
class DeferClass {
public:
    /**
     * @brief 构造函数，注册延迟执行的函数
     * @param f 待执行的函数对象（支持右值引用）
     * std::forward<F>(f) 是 C++ 中用于实现完美转发的函数
     * 在模板函数中，根据模板参数 F 的类型，将参数 f 以其原始的值类别（左值或右值）转发给其他函数
     * 确保转发过程中不丢失参数的左值 / 右值属性
     * 这里的f虽然绑定到右值，但是作为函数参数始终是命名变量，属于左值
     */
    DeferClass(F&& f) : m_func(std::forward<F>(f)) {}

    /**
     * @brief 构造函数，注册延迟执行的函数
     * @param f 待执行的函数对象（支持左值引用）
     */
    DeferClass(const F& f) : m_func(f) {}

    /**
     * @brief 析构函数，自动执行注册的函数
     */
    ~DeferClass() noexcept { m_func(); }
    
    // 禁止拷贝和赋值，避免函数被多次执行
    DeferClass(const DeferClass&) = delete;
    DeferClass& operator=(const DeferClass&) = delete;

    // 允许移动
    DeferClass(DeferClass&&) = default;
    DeferClass& operator=(DeferClass&&) = default;

private:
    F m_func;  ///< 存储待执行的函数对象
};

/**
 * @brief 简化DeferClass使用的宏定义
 * @details 自动生成唯一变量名，在当前作用域结束时执行函数
 * @example DEFER [fp]() {  // 仅捕获需要的变量fp，避免意外捕获
                if (fp) fclose(fp);
            }; // 作用域结束时关闭文件描述符
 */
#define CONCAT(a, b) a##b
#define MAKE_DEFER(line) DeferClass CONCAT(defer_, line) = 

#undef DEFER
#define DEFER MAKE_DEFER(__LINE__)


/**
 * @brief 调试日志打印函数
 * @details 仅在DEBUG为true时生效，输出带时间戳的日志信息
 * @param format 日志格式字符串
 * @param ... 可变参数列表
 */
void DPrintf(const char* format, ...);

/**
 * @brief 断言工具函数
 * @details 条件不满足时输出错误信息并终止程序，用于检查不可恢复的错误
 * @param condition 断言条件
 * @param message 错误提示信息
 */
void Assert(bool condition, const std::string& message = "Assertion failed!");

/**
 * @brief 字符串格式化函数
 * @details 类似printf的格式化功能，返回格式化后的字符串
 * @tparam Args 可变参数类型
 * @param format_str 格式字符串
 * @param args 可变参数列表
 * @return 格式化后的字符串
 */
template <typename... Args>
std::string Format(const char* format_str, Args&&... args) {
    // 计算所需缓冲区大小（包含'\0'）
    int buffer_size = std::snprintf(nullptr, 0, format_str, std::forward<Args>(args)...) + 1;
    if (buffer_size <= 0) {
        throw std::runtime_error("Formatting failed: invalid format string or arguments");
    }

    size_t size = static_cast<size_t>(buffer_size);

    // 分配缓冲区并格式化
    std::string buf;
    buf.resize(size);

    int result = std::snprintf(buf.data(), size, format_str, std::forward<Args>(args)...);
    if (result < 0 || static_cast<size_t>(result) != size - 1) {
        throw std::runtime_error("Failed to write formatted string");
    }

    // 移除null终止符，直接返回string（避免额外拷贝）
    buf.pop_back();  // 等价于取[0, size-1)范围
    return buf;
}

/**
 * @brief 获取当前系统时间点
 * @return 表示当前时间的time_point对象
 */
std::chrono::system_clock::time_point Now();

/**
 * @brief 生成随机选举超时时间
 * @details 在[MIN_RANDOMIZED_ELECTION_TIME, MAX_RANDOMIZED_ELECTION_TIME]范围内生成随机值
 * @return 随机超时时间（毫秒）
 */
std::chrono::milliseconds GetRandomizedElectionTimeout();

/**
 * @brief 线程休眠指定毫秒数
 * @param ms 休眠时间（毫秒）
 */
void SleepMs(int ms);

/**
 * @brief 线程安全队列 异步写日志队列
 * @details 支持多线程并发读写的队列，用于线程间通信
 * @tparam T 队列中元素的类型
 */
 template <typename T>
 class LockQueue {
 public:
    /**
     * @brief 入队操作
     * @param data 待入队的元素
     * @note 非阻塞，入队后唤醒一个等待的消费者
     */
    void Push(const T& data) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push(data);
        m_cond.notify_one();
    }
     
    /**
     * @brief 出队操作（阻塞式）
     * @details 若队列为空则阻塞等待，直到有元素入队
     * @return 出队的元素
     */
    T Pop() {
        std::unique_lock<std::mutex> lock(m_mutex);     // 有条件变量等待的一般用unique_lock，可以手动释放锁
        m_cond.wait(lock, [this]() { return !m_queue.empty(); });
        
        T data = m_queue.front();
        m_queue.pop();
        return data;
    }
     
    /**
     * @brief 出队操作（超时式）
     * @details 若队列为空则等待指定时间，超时后返回false
     * @param timeout_ms 超时时间（毫秒）
     * @param result 用于存储出队元素的指针
     * @return 成功出队返回true，超时返回false
     */
    bool TimeoutPop(int timeout_ms, T* result) {
        std::unique_lock<std::mutex> lock(m_mutex);
        auto timeout = std::chrono::milliseconds(timeout_ms);
        
        bool has_data = m_cond.wait_for(
            lock, timeout, [this]() { return !m_queue.empty(); }
        );
        
        if (!has_data) {
            return false;
        }
        
        *result = m_queue.front();
        m_queue.pop();
        return true;
    }
 
private:
    std::queue<T> m_queue;               // 底层存储队列
    std::mutex m_mutex;                  // 互斥锁，保证线程安全
    std::condition_variable m_cond;      // 条件变量，用于等待通知
};

/**
 * @brief KV操作指令（用于Raft日志序列化）
 * @details 封装Get/Put/Append等操作，支持序列化传输
 */
class Op {
public:
    std::string operation;  // 操作类型："Get" "Put" "Append"
    std::string key;        // 键
    std::string value;      // 值（Get操作可空）
    std::string client_id;  // 客户端ID
    int request_id;         // 请求ID（用于去重）
    
    /**
     * @brief 序列化为字符串
     * @return 序列化后的字符串
     */
    std::string AsString() const;
    
    /**
     * @brief 从字符串反序列化
     * @param str 序列化后的字符串
     * @return 成功返回true，失败返回false
     */
    bool ParseFromString(const std::string& str);
    
    // 输出操作符重载
    friend std::ostream& operator<<(std::ostream& os, const Op& op);
    
private:
    // Boost序列化支持
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & operation;
        ar & key;
        ar & value;
        ar & client_id;
        ar & request_id;
    }
};

// kvServer之间的通讯情况
const std::string OK = "OK";
const std::string ErrNoKey = "ErrNoKey";
const std::string ErrWrongLeader = "ErrWrongLeader";

/**
 * @brief 检查端口是否可用
 * @param port 待检查的端口号
 * @return 可用返回true，否则返回false
 */
bool IsPortAvailable(unsigned short port);

/**
 * @brief 获取可用端口
 * @param port 输出参数，返回找到的可用端口
 * @return 成功找到返回true，否则返回false
 */
bool GetAvailablePort(short& port);

}   //namespace common

#endif  // COMMON_UTIL_H